/*
 * Javlov - a Java toolkit for reinforcement learning with multi-agent support.
 * 
 * Copyright (c) 2009 Matthijs Snel
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package net.javlov.util;

public class ArrayUtil {
	
	public static String arrayToString( double[] d) {
		String s = "";
		for ( int i = 0; i < d.length; i++ )
			s += d[i] + " ";
		return s;
	}
	
	public static String arrayToString( double[][] A, int opt) {
		String s = "";
		int m = A.length;
		if ( opt == 1 )
			for ( int i = 0; i < m; i++ ) {
				try {
					for ( int j = 0; j < A[i].length; j++ )
						if (j == (A[i].length-1))
							s += A[i][j] + "\n";
						else
							s += A[i][j] + " ";
				} catch (NullPointerException e) {
					System.err.println("NULLPOINTER EXCEPT AT i=" + i);
				}
			}
		else if ( opt == 2 )
			for ( int j = 0; j < A[0].length; j++ )
				for ( int i = 0; i < m; i++ )
					if (i == (m-1))
						s += A[i][j] + "\n";
					else
						s += A[i][j] + " ";
		return s;
	}
	
	public static String arrayToString( int[] d) {
		String s = "";
		for ( int i = 0; i < d.length; i++ )
			s += d[i] + " ";
		return s;
	}
	
	public static String arrayToString( int[][] A, int opt) {
		String s = "";
		int m = A.length;
		int n = A[0].length;
		if ( opt == 1 )
			for ( int i = 0; i < m; i++ )
				for ( int j = 0; j < n; j++ )
					if (j == (n-1))
						s += A[i][j] + "\n";
					else
						s += A[i][j] + " ";
		else if ( opt == 2 )
			for ( int j = 0; j < n; j++ )
				for ( int i = 0; i < m; i++ )
					if (i == (m-1))
						s += A[i][j] + "\n";
					else
						s += A[i][j] + " ";  
		return s;
	}
	
	public static String arrayToString( Object[] o) {
		String s = "";
		for ( int i = 0; i < o.length; i++ )
			s += o[i] + " ";
		return s;
	}
	
	public static int binaryToInt( int bin[] ) {
		int r = 0, pos = 0;
		for ( int i = bin.length - 1; i >= 0; i--)
			r += bin[i]*Math.pow(2,pos++);
		return r;
	}
	
	public double[] concat( double a[], double b[] ) {
		double r[] = new double[a.length + b.length];
		System.arraycopy(a, 0, r, 0, a.length);
		System.arraycopy(b, 0, r, a.length, b.length);
		return r;
	}
	
	public static double[] diff( double[] a, double[] b) {
		double r[] = new double[a.length];
		for ( int i = 0; i < a.length; i++ )
			r[i] = a[i] - b[i];
		return r;		
	}
	
	public static double[] div ( int[] a, double d ) {
		double r[] = new double[a.length];
		for ( int i = 0; i < a.length; i++ )
			r[i] = a[i] / d;
		return r;		
	}
	
	public static double[] div ( double[] a, int d ) {
		double r[] = new double[a.length];
		for ( int i = 0; i < a.length; i++ )
			r[i] = a[i] / d;
		return r;		
	}
	
	public static double max( double[] d ) {
		double max = Double.NEGATIVE_INFINITY;
		for ( int i = 0; i < d.length; i++ )
			if ( d[i] > max )
				max = d[i];
		return max;
	}
	
	public static int max( int[] d ) {
		int max = Integer.MIN_VALUE;
		for ( int i = 0; i < d.length; i++ )
			if ( d[i] > max )
				max = d[i];
		return max;
	}
	
	public static int maxIndex( double[] d ) {
		int maxpos = 0;
		for ( int i = 0; i < d.length; i++ )
			if ( d[i] >= d[maxpos] )
				maxpos = i;
		return maxpos;
	}
	
	public static int maxIndex( int[] d ) {
		int maxpos = 0;
		for ( int i = 0; i < d.length; i++ )
			if ( d[i] >= d[maxpos] )
				maxpos = i;
		return maxpos;
	}
	
	public static int[] multimaxIndex( double[] d ) {
		int maxpos[] = new int[d.length],
			lastpos = 0;
		double maxval = Double.NEGATIVE_INFINITY;
		for ( int i = 0; i < d.length; i++ )
			if ( d[i] > maxval ) {
				maxval = d[i];
				maxpos = new int[d.length - i];
				lastpos = 0;
				maxpos[lastpos++] = i;
			} else if ( d[i] == maxval ) {
				maxpos[lastpos++] = i;
			}
		int r[] = new int[lastpos];
		System.arraycopy(maxpos, 0, r, 0, lastpos);
		return r;
	}
	
	public static int[] multimaxIndex( int[] d ) {
		int maxpos[] = new int[d.length],
			lastpos = 0,
			maxval = Integer.MIN_VALUE;
		for ( int i = 0; i < d.length; i++ )
			if ( d[i] > maxval ) {
				maxval = d[i];
				maxpos = new int[d.length - i];
				lastpos = 0;
				maxpos[lastpos++] = i;
			} else if ( d[i] == maxval ) {
				maxpos[lastpos++] = i;
			}
		int r[] = new int[lastpos];
		System.arraycopy(maxpos, 0, r, 0, lastpos);
		return r;
	}
	
	public static double[] subArray( double a[], int start, int len ) {
		double r[] = new double[len];
		System.arraycopy(a, start, r, 0, len);
		return r;
	}
	
	public static int[] subArray( int a[], int start, int len ) {
		int r[] = new int[len];
		System.arraycopy(a, start, r, 0, len);
		return r;
	}
	
	public static int[] sum( int[][] a, int l ) {
		int r[] = new int[l];
		for ( int j = 0; j < l; j++ )
			for ( int i = 0; i < a.length; i++ )
				r[j] += a[i][j];
		return r;
	}
	
	public static double[] sum( double[][] a, int l ) {
		double r[] = new double[l];
		for ( int j = 0; j < l; j++ )
			for ( int i = 0; i < a.length; i++ )
				r[j] += a[i][j];
		return r;
	}
	
	public static double sum( double [] d ) {
		double r = 0;
		for ( int i = 0; i < d.length; i++ )
			r += d[i];
		return r;
	}
	
	public static int sum( int [] d ) {
		int r = 0;
		for ( int i = 0; i < d.length; i++ )
			r += d[i];
		return r;
	}
	
	public static void sumeachInPlace( double [] d ) {
		for ( int i = 1; i < d.length; i++ )
			d[i] = d[i-1] + d[i];
	}
	
	public static void sumeachInPlace( int [] d ) {
		for ( int i = 1; i < d.length; i++ )
			d[i] = d[i-1] + d[i];
	}
	
	public static double[] sumeach( double [] d ) {
		double r[] = new double[d.length];
		r[0] = d[0];
		for ( int i = 1; i < d.length; i++ )
			r[i] = d[i-1] + d[i];
		return r;
	}
	
	public static int[] sumeach( int [] d ) {
		int r[] = new int[d.length];
		r[0] = d[0];
		for ( int i = 1; i < d.length; i++ )
			r[i] = d[i-1] + d[i];
		return r;
	}
	
	public static double sumexp( double [] d ) {
		double r = 0;
		for ( int i = 0; i < d.length; i++ )
			r += Math.exp(d[i]);
		return r;
	}
	
	public static double sumexp( int [] d ) {
		double r = 0;
		for ( int i = 0; i < d.length; i++ )
			r += Math.exp(d[i]);
		return r;
	}
}
